package net.atos.java.example.boodschappen.client;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import net.atos.java.example.boodschappen.model.Boodschap;
import net.atos.java.example.boodschappen.model.HoeveelheidEenheid;
import net.atos.java.example.boodschappen.shared.BoodschappenService;
import net.atos.java.example.boodschappen.shared.BoodschappenServiceAsync;

import com.google.gwt.cell.client.FieldUpdater;
import com.google.gwt.cell.client.SelectionCell;
import com.google.gwt.cell.client.TextInputCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.view.client.ListDataProvider;

/**
 * Paneel voor nieuwe boodschappen.
 * 
 * @author Pal Hargitai
 */
public class NieuweBoodschappenPanel extends PopupPanel {

	/** Boodschappen service. */
	private BoodschappenServiceAsync boodschappenService = GWT.create(BoodschappenService.class);
	/** Boodschappen aanbieder. */
	private ListDataProvider<Boodschap.Builder> boodschapProvider;
	/** Ophalen terug koppeling. */
	private AsyncCallback<List<Boodschap>> ophalenBoodschappenCallback;

	/**
	 * Nieuwe boodschappen paneel.
	 * @param callback Terug koppeling als het bewerken klaar is.
	 */
	public NieuweBoodschappenPanel(AsyncCallback<List<Boodschap>> callback) {
		super(true);
		Grid grid = new Grid(3, 1);
		add(grid);

		grid.setWidget(1, 0, new Button("Extra Boodschap", new BoodschapToevoegenHandler()));
		grid.setWidget(2, 0, new Button("Toevoegen", new ToevoegenHandler()));

		// Tabel.
		CellTable<Boodschap.Builder> boodschappenTable = new CellTable<Boodschap.Builder>();
		boodschappenTable.addColumn(new BoodschapNaamColumn());
		boodschappenTable.addColumn(new BoodschapHoeveelheidColumn());
		boodschappenTable.addColumn(new BoodschapEenheidColumn());
		// Data aanbieder.
		boodschapProvider = new ListDataProvider<Boodschap.Builder>(new LinkedList<Boodschap.Builder>());
		boodschapProvider.getList().add(new Boodschap.Builder());
		boodschapProvider.addDataDisplay(boodschappenTable);
		grid.setWidget(0, 0, boodschappenTable);

		this.ophalenBoodschappenCallback = callback;
	}

	/**
	 * Naam kolom.
	 * 
	 * @author Pal Hargitai
	 */
	public class BoodschapNaamColumn extends Column<Boodschap.Builder, String> {
		/** Default constructor. */
		public BoodschapNaamColumn() {
			super(new TextInputCell());
			setFieldUpdater(new BoodschapNaamUpdate());
		}

		/** {@inheritDoc} */
		@Override
		public String getValue(Boodschap.Builder object) {
			return object.getBoodschap();
		}
	}

	/**
	 * Hoeveelheid kolom.
	 * 
	 * @author Pal Hargitai
	 */
	public class BoodschapHoeveelheidColumn extends Column<Boodschap.Builder, String> {
		/** Default constructor. */
		public BoodschapHoeveelheidColumn() {
			super(new TextInputCell());
			setFieldUpdater(new BoodschapHoeveelheidUpdate());
		}

		/** {@inheritDoc} */
		@Override
		public String getValue(Boodschap.Builder object) {
			if (object.getHoeveelheid() == null) {
				return null;
			} else {
				return object.getHoeveelheid().toString();
			}
		}
	}

	/**
	 * Eenheid kolom.
	 * 
	 * @author Pal Hargitai
	 */
	public class BoodschapEenheidColumn extends Column<Boodschap.Builder, String> {
		/** Default constructor. */
		public BoodschapEenheidColumn() {
			super(new SelectionCell(HoeveelheidEenheid.EENHEDEN));
			setFieldUpdater(new BoodschapEenheidUpdate());
		}

		/** {@inheritDoc} */
		@Override
		public String getValue(Boodschap.Builder object) {
			if (object.getEenheid() == null) {
				return "";
			} else {
				return object.getEenheid().name();
			}
		}
	}

	/**
	 * Naam bewerk terug koppeling.
	 * 
	 * @author Pal Hargitai
	 */
	public class BoodschapNaamUpdate implements FieldUpdater<Boodschap.Builder, String> {
		/** {@inheritDoc} */
		@Override
		public void update(int index, Boodschap.Builder object, String value) {
			object.naam(value);
		}
	}

	/**
	 * Hoeveelheid bewerking.
	 * 
	 * @author Pal Hargitai
	 */
	public class BoodschapHoeveelheidUpdate implements FieldUpdater<Boodschap.Builder, String> {
		/** {@inheritDoc} */
		@Override
		public void update(int index, Boodschap.Builder object, String value) {
			if (value == null || "".equals(value)) {
				object.hoeveelheid(new BigDecimal(0));
			} else {
				object.hoeveelheid(new BigDecimal(value));
			}
		}
	}

	/**
	 * Eenheid bewerking.
	 * 
	 * @author Pal Hargitai
	 */
	public class BoodschapEenheidUpdate implements FieldUpdater<Boodschap.Builder, String> {
		/** {@inheritDoc} */
		@Override
		public void update(int index, Boodschap.Builder object, String value) {
			if (value == null || "".equals(value)) {
				object.hoeveelheidEenheid(HoeveelheidEenheid.GRAM);
			} else {
				object.hoeveelheidEenheid(HoeveelheidEenheid.valueOf(value));
			}
		}
	}

	/**
	 * Boodschap toevoegen knop.
	 * 
	 * @author Pal Hargitai
	 */
	public class ToevoegenHandler implements ClickHandler {
		/** {@inheritDoc} */
		@Override
		public void onClick(ClickEvent event) {
			List<Boodschap> boodschappen = new ArrayList<Boodschap>(boodschapProvider.getList().size());
			for (Boodschap.Builder builder : boodschapProvider.getList()) {
				boodschappen.add(builder.build());
			}
			boodschappenService.toevoegenBoodschappen(boodschappen, new NieuweBoodschappenCallback());
		}
	}

	/**
	 * Boodschap toevoegen terug koppeling.
	 * 
	 * @author Pal Hargitai
	 */
	public class BoodschapToevoegenHandler implements ClickHandler {
		/** {@inheritDoc} */
		@Override
		public void onClick(ClickEvent event) {
			boodschapProvider.getList().add(new Boodschap.Builder());
			boodschapProvider.flush();
		}
	}

	/**
	 * Nieuwe boodschap terug koppeling.
	 * 
	 * @author Pal Hargitai
	 */
	public class NieuweBoodschappenCallback implements AsyncCallback<Void> {
		/** {@inheritDoc} */
		@Override
		public void onFailure(Throwable caught) {
			Window.alert(caught.getMessage());
		}

		/** {@inheritDoc} */
		@Override
		public void onSuccess(Void result) {
			NieuweBoodschappenPanel.this.hide();
			boodschappenService.ophalenBoodschappen(ophalenBoodschappenCallback);
		}
	}
}
